use std::rc::Rc;
use super::Texture;
use zmath::Vec2;
use crate::graphics::TextureFormat;
use crate::VertexLayout::P;

pub struct FrameBuffer {
    id: u32,
    target: Rc<Texture>,
}

impl FrameBuffer {
    pub fn new(extent: Vec2) -> Self {
        let id = unsafe {
            let mut fbo = 0u32;
            gl::GenFramebuffers(1, &mut fbo);
            gl::BindFramebuffer(gl::FRAMEBUFFER, fbo);
            fbo
        };

        let target = Texture::new(extent.0 as u32, extent.1 as u32, TextureFormat::RGB);

        unsafe {
            gl::BindTexture(gl::TEXTURE_2D, target.id());
            gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, target.id(), 0);
            gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
        }

        Self {
            id,
            target,
        }
    }

    pub fn texture(&self) -> Rc<Texture> {
        self.target.clone()
    }

    pub fn draw<F>(&self, mut draw: F) where F: FnMut() -> () {
        self.bind();
        draw();
        self.unbind();
    }

    pub fn bind(&self) {
        unsafe {
            gl::BindFramebuffer(gl::FRAMEBUFFER, self.id);
            gl::Enable(gl::DEPTH_TEST);
        }
    }

    pub fn unbind(&self) {
        unsafe {
            gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
            gl::Disable(gl::DEPTH_TEST);
        }
    }
}